﻿using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using Newtonsoft.Json;

namespace SocialKit.SinaWeibo.Api.Models
{
    /// <summary>
    /// 表示新浪微博用户信息。
    /// </summary>
    [Serializable]
    [JsonObject("user")]
    public class User
    {
        /// <summary>
        /// 获取或设置当前用户信息的ID。
        /// </summary>
        [JsonProperty("id")]
        public long Id { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的昵称。
        /// </summary>
        [JsonProperty("screen_name")]
        public string ScreenName { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的友好显示名称。
        /// </summary>
        [JsonProperty("name")]
        public string Name { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的省份编码。
        /// </summary>
        [JsonProperty("province")]
        public int? ProvinceId { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的城市编码。
        /// </summary>
        [JsonProperty("city")]
        public int? CityId { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的地址。
        /// </summary>
        [JsonProperty("location")]
        public string Location { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的个人描述。
        /// </summary>
        [JsonProperty("description")]
        public string Description { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的博客地址。
        /// </summary>
        [JsonProperty("url")]
        public string BlogUrl { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的自定义头像图片地址。
        /// </summary>
        [JsonProperty("profile_image_url")]
        public string ProfileImage { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的自定义微博地址域名。
        /// </summary>
        [JsonProperty("domain")]
        public string ProfileDomain { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的性别。
        /// </summary>
        [JsonProperty("gender")]
        public Gender Gender { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的粉丝数量。
        /// </summary>
        [JsonProperty("followers_count")]
        public long? FollowerCount { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的关注数量。
        /// </summary>
        [JsonProperty("friends_count")]
        public long? FriendCount { get; set; }

        /// <summary>
        /// 获取或设置当前用户发布的新浪微博的数量。
        /// </summary>
        [JsonProperty("statuses_count")]
        public long? StatusCount { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的创建时间。
        /// </summary>
        [JsonProperty("created_at"), JsonConverter(typeof(Extensions.JsonDateTimeConverter))]
        public DateTime? CreatedAt { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息的收藏数量。
        /// </summary>
        [JsonProperty("favourites_count")]
        public long? FavouriteCount { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息是否被当前登录用户关注。
        /// </summary>
        [JsonProperty("following")]
        public bool IsFollowing { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息是否通过认证。
        /// </summary>
        [JsonProperty("verified")]
        public bool IsVerified { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息是否allow_all_act_msg。
        /// </summary>
        [JsonProperty("allow_all_act_msg")]
        public bool IsAllowAllActMessage { get; set; }

        /// <summary>
        /// 获取或设置当前用户信息是否启用了地理位置。
        /// </summary>
        [JsonProperty("geo_enabled")]
        public bool IsGeoEnabled { get; set; }

        string province;

        /// <summary>
        /// 获取当前用户信息的省份名称。
        /// </summary>
        public string Province
        {
            get
            {
                if (province == null)
                    province = UserHelper.GetProvince(this.ProvinceId);

                return province;
            }
        }

        string city;

        /// <summary>
        /// 获取当前用户信息的城市名称。
        /// </summary>
        public string City
        {
            get
            {
                if (city == null)
                    city = UserHelper.GetCity(this.ProvinceId, this.CityId);

                return city;
            }
        }

        /// <summary>
        /// 返回当前用户的昵称。
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return this.ScreenName;
        }
    }

    /// <summary>
    /// 表示性别。
    /// </summary>
    public enum Gender
    {
        /// <summary>
        /// 表示男性。
        /// </summary>
        M,

        /// <summary>
        /// 表示女性。
        /// </summary>
        F,

        /// <summary>
        /// 表示性别未知。
        /// </summary>
        N
    }

    /// <summary>
    /// 用户信息辅助类。
    /// </summary>
    internal static class UserHelper
    {
        /// <summary>
        /// 从资源中获取XML。
        /// </summary>
        /// <returns></returns>
        static string GetProvincesXml()
        {
            using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SocialKit.SinaWeibo.Api.provinces.xml"))
            {
                using (var reader = new StreamReader(stream))
                {
                    return reader.ReadToEnd();
                }
            }
        }

        /// <summary>
        /// 获取省份名称。
        /// </summary>
        /// <param name="provinceId">用户信息的省份ID。</param>
        /// <returns></returns>
        public static string GetProvince(int? provinceId)
        {
            if (!provinceId.HasValue)
                return string.Empty;

            return (from x in XElement.Parse(GetProvincesXml()).Elements("province")
                    where Convert.ToInt32(x.Attribute("id").Value) == provinceId.Value
                    select x.Attribute("name").Value).FirstOrDefault();
        }

        /// <summary>
        /// 获取城市名称。
        /// </summary>
        /// <param name="provinceId">用户信息的省份ID。</param>
        /// <param name="cityId">用户信息的城市ID。</param>
        /// <returns></returns>
        public static string GetCity(int? provinceId, int? cityId)
        {
            if (!provinceId.HasValue || !cityId.HasValue)
                return string.Empty;

            return (from cx in
                        (from x in XElement.Parse(GetProvincesXml()).Elements("province")
                         where Convert.ToInt32(x.Attribute("id").Value) == provinceId.Value
                         select x).Elements("city")
                    where Convert.ToInt32(cx.Attribute("id").Value) == cityId.Value
                    select cx.Attribute("name").Value).FirstOrDefault();
        }
    }
}